package ysq.xyg.base.extend.netty;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.concurrent.GlobalEventExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ysq.xyg.base.util.BaseConstant;
import ysq.xyg.base.util.BaseUtil;
import ysq.xyg.base.util.SpringApplicationContextUtil;
import ysq.xyg.web.model.po.WebChat;
import ysq.xyg.web.model.vo.WebChatVo;
import ysq.xyg.web.service.WebChatService;

import javax.annotation.Resource;
import java.util.*;

/**
 * netty长连接handler实现
 *
 * @author taocongcong
 * @create 2019-03-12 14:47
 */
public class WebSocketServerHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    private static Logger logger = LoggerFactory.getLogger(WebSocketServerHandler.class);

    private WebChatService webChatService= (WebChatService)SpringApplicationContextUtil.getBean("webChatService");

    /**
     * 不同组怎么处理
     */
    public static ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    /**
     * key是组名，value是组内成员
     */
    public static Map<String, ChannelGroup> channelGroupMap = new HashMap<String, ChannelGroup>();

    /**
     * key用户id
     */
    public static Map<String, Channel> userChannelMap = new HashMap<String, Channel>();

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
        //将消息转换为对象
        WebChat webChat=JSON.parseObject(msg.text(),WebChat.class);
        userChannelMap.put(webChat.getSendId(),ctx.channel());
        webChat.setId(BaseUtil.uId());
        webChat.setCreateTime(new Date());
        webChat.setUpdateTime(new Date());
        webChat.setRemoveTag(BaseConstant.BASE_REMOVE_TAG_NORMAL);
        webChatService.insert(webChat);
        //给接收对象发消息
        Channel receiverChat=userChannelMap.get(webChat.getReceiverId());
        List<WebChat> list=webChatService.listLeft(new WebChatVo(webChat.getId()));
        if(list!=null&&list.size()>0){
            String text = JSON.toJSONString(list.get(0));
            if(receiverChat!=null&&receiverChat.isActive()){
                receiverChat.writeAndFlush(new TextWebSocketFrame(text));
            }
            ctx.channel().writeAndFlush(new TextWebSocketFrame(text));
        }

    }

    /**
     * 连接建立时
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        System.out.println("handlerAddred " + ctx.channel().id().asLongText());
        // 获取连接的channel
        Channel incomming = ctx.channel();
        // 通知所有已经连接到服务器的客户端，有一个新的通道加入
        /*for (Channel channel : channels) {
            System.out.print("[SERVER]-"+incomming.remoteAddress()+"加入\n");
        }*/
        logger.info("[SERVER]-"+incomming.remoteAddress()+"加入\n");
        channels.add(ctx.channel());

        //userChannelMap.put(String.valueOf(userId), incomming);
    }

    /**
     * 连接关闭时
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        System.out.println("handlerRemoved " + ctx.channel().id().asLongText());
        //获取连接的channel
        Channel incomming = ctx.channel();
        /*for (Channel channel : channels) {
            channel.writeAndFlush("[SERVER]-"+incomming.remoteAddress()+"离开\n");
        }*/
        logger.info("[SERVER]-"+incomming.remoteAddress()+"离开\n");
        //从服务端的channelGroup中移除当前离开的客户端
        channels.remove(ctx.channel());
        //userChannelMap.remove(String.valueOf(userId));
        // 关闭其他
        String userId = "";
        if (userChannelMap != null && userChannelMap.size() > 0) {
            Iterator<Map.Entry<String, Channel>> it = userChannelMap.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry<String, Channel> entry = it.next();
                if (entry.getValue() == ctx.channel()) {
                    // 删除元素
                    it.remove();
                    userId = entry.getKey();
                }
            }
        }
        if (channelGroupMap != null && channelGroupMap.size() > 0) {
            for (Map.Entry<String, ChannelGroup> entry : channelGroupMap.entrySet()) {
                ChannelGroup value = entry.getValue();
                value.remove(ctx.channel());
            }
        }
    }

    /**
     * 异常发生时
     *
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println("异常发生");
        ctx.close();
    }
}
